﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Xty.MSBuilder
{
    class Program
    {
        private static HttpListener httpListener = new HttpListener();
        private static ConfigInfo config = null;
        static void Main(string[] args)
        {
            if (!HttpListener.IsSupported)
            {
                //该类只能在Windows xp sp2或者Windows server 200 以上的操作系统中才能使用，因为这个类必须使用Http.sys系统组件才能完成工作
                //。所以在使用前应该先判断一下是否支持该类
                Console.WriteLine("操作系统不支持 HttpListener");
                Console.WriteLine("按任意键退出......");
                Console.ReadKey();
            }
            else
            {
                var configFilePath = "MSBuilder.config";
                // 读取配置
                try
                {
                    using (var fs = new FileStream(configFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(ConfigInfo));
                        config = (ConfigInfo)serializer.Deserialize(fs);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("加载配置文件 Exception:" + ex.Message);
                }

                if (config != null)
                {
                    //设置前缀，必须以‘/’结尾
                    var url = config.AddressText.Trim('/') + "/";
                    httpListener.Prefixes.Add(url);
                    httpListener.Start();

                    Console.WriteLine($"{DateTime.Now.ToString()} 服务端 {url} 初始化完毕，正在等待客户端请求");

                    var httpServer = new Thread(new ThreadStart(HttpRequestServer));
                    httpServer.Start();
                }
                else
                {
                    Console.WriteLine("按任意键退出......");
                    Console.ReadKey();
                }
            }
        }

        private static void HttpRequestServer()
        {
            while (true)
            {
                // 子线程处理请求
                var threadHttpRequestHandle = new Thread(new ParameterizedThreadStart((requestContext) =>
                {
                    var context = (HttpListenerContext)requestContext;

                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 接收到 {context.Request.HttpMethod} 请求.");
                    var result = "";

                    var token = context.Request.QueryString["token"];
                    if (!string.IsNullOrEmpty(token) && token == config.Token)
                    {
                        var serviceName = context.Request.QueryString["name"];
                        if (!string.IsNullOrEmpty(serviceName))
                        {
                            var service = config.Services.Find(m => m.Name.ToLower() == serviceName.ToLower());
                            if (service != null)
                            {
                                if (!service.IsRunning)
                                {
                                    service.IsRunning = true;

                                    (new Thread(new ParameterizedThreadStart(Excute))).Start(service);

                                    result = "OK";
                                }
                                else
                                {
                                    result = $"service 正在执行";
                                }
                            }
                            else
                            {
                                result = $"service {serviceName} 不存在";
                            }
                        }
                        else
                        {
                            result = "缺少 name 参数";
                        }
                    }
                    else
                    {
                        result = "缺少 token 参数或 token 不正确";
                    }

                    //Response
                    context.Response.StatusCode = 200;
                    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                    context.Response.ContentType = "text/html; charset=utf-8";
                    context.Response.ContentEncoding = Encoding.UTF8;

                    byte[] buffer = Encoding.UTF8.GetBytes(result);
                    context.Response.ContentLength64 = buffer.Length;
                    var output = context.Response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    output.Close();

                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 返回 {result}");
                }));

                threadHttpRequestHandle.Start(httpListener.GetContext());
            }
        }

        private static void Excute(object serviceObject)
        {
            if (serviceObject == null)
                return;

            var service = (ServiceInfo)serviceObject;

            try
            {
                string dir = Path.GetDirectoryName(service.Path);
                string fileName = Path.GetFileName(service.Path);

                var proc = new Process();
                proc.StartInfo.WorkingDirectory = dir;
                proc.StartInfo.FileName = fileName;
                //这里设置DOS窗口不显示
                //proc.StartInfo.CreateNoWindow = true;
                //proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                proc.Start();
                proc.WaitForExit();
                proc.Close();

                // 钉钉发送
                SendDingtalkMsg(service.Dingtalk, $"{service.Name} 执行成功");

                service.IsRunning = false;
            }
            catch (Exception ex)
            {
                SendDingtalkMsg(service.Dingtalk, $"{service.Name} 执行失败，{ex.Message}");
            }

        }

        static void SendDingtalkMsg(string api, string msg)
        {
            using (var client = new HttpClient())
            {
                try
                {
                    var json = "{\"msgtype\":\"text\",\"text\":{\"content\":\"" + msg + "\"}}";

                    var content = new StringContent(json);
                    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                    var response = client.PostAsync(api, content).Result;
                    response.EnsureSuccessStatusCode();
                    string responseBody = response.Content.ReadAsStringAsync().Result;

                    Console.WriteLine($"{DateTime.Now.ToString()} 发送钉钉消息成功，{responseBody}");
                }
                catch (Exception e)
                {
                    Console.WriteLine($"{DateTime.Now.ToString()} 发送钉钉消息失败，Message:{e.Message}");
                }
            }
        }
    }
}
